

#include "MsgQueue.h"
#include "cc_pub.h"
// #include "basic_api.h"
#include "cc_malloc.h"	// 依赖 malloc/free 


#define CFG_RWLOCK_CHECK 

#define LLOG
#define LLOG_ERR
#define LLOG_MARK
#include "llog.h"

#ifdef	CFG_SYS_MALLOC
#define L_MALLOC 	MALLOC
#define L_FREE 		MFREE

#else

#include <stdlib.h>
#define L_MALLOC(A) malloc(A)
#define L_FREE(A)	free(A)
#endif
/********* interior  struct **********/
struct CC_Msg_Queue_By_Pointer{
    uint8_t* pBuf;
	uint32_t BufSz;
	
	uint32_t ItemSz;
	uint32_t ItemNum ; // IndexMax

	uint32_t wIndex;         
    uint32_t rIndex;
	
	uint8_t  RWLock;
} ;

/********** global val ***************/

/******* local function **************/

/******* TODO ************************/

#ifdef CFG_MSG_QUEUE

void MsgQueue_ShowObj(tMsgQueue* pObj){
    LLOG("tMsgQueue\n");
	LLOG("pBuf	  =[%x]\n",pObj->pBuf	);
	LLOG("BufSz	  =[%d]\n",pObj->BufSz	);
	LLOG("ItemSz  =[%d]\n",pObj->ItemSz	);
	LLOG("ItemNum =[%d]\n",pObj->ItemNum);
	LLOG("wIndex  =[%d]\n",pObj->wIndex	);
	LLOG("rIndex  =[%d]\n",pObj->rIndex	);
	LLOG("RWLock  =[%d]\n",pObj->RWLock	);	
}

tMsgQueue* MsgQueue_Create(uint32_t ItemNum){
	
	uint32_t ItemSz;
	tMsgQueue* ptmp = NULL;
	uint8_t* pBuf = NULL;

	if( ItemNum == 0){
		return ptmp;
	}
	
	ItemSz = sizeof(uint8_t*);
	
	ptmp = (tMsgQueue*)L_MALLOC(sizeof(tMsgQueue));
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	pBuf = L_MALLOC(ItemNum*ItemSz);
	if(pBuf == NULL){
		L_FREE(ptmp);
		LLOG_ERR();
		return NULL;
	}
	
	MEMSET((uint8_t*)ptmp,0,sizeof(tMsgQueue));
	
	ptmp->pBuf 	= pBuf;
	ptmp->ItemNum = ItemNum; 
	ptmp->ItemSz = ItemSz; 
	ptmp->BufSz = ItemNum*ItemSz; 

	return ptmp;
}

uint32_t MsgQueue_Write(tMsgQueue* pObj,uint32_t dLen, uint8_t* pPkg){

	uint8_t* ptmp = NULL;
	
	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t LoopSz;

    uint32_t CopySz;
    uint32_t ItemSz;	
    
	CopySz=0;
    if( (pObj== NULL) || (pPkg == NULL) || (dLen == 0) ){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC(CopySz,wIndex,rIndex,LoopSz);		 // empty 
	CopySz -= 1;
	
	if(CopySz == 0){
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}
	//
	ptmp = L_MALLOC(dLen+sizeof(uint32_t));
	if(ptmp == NULL){
		pObj->RWLock=0;
		CopySz = 0;
		LLOG_ERR();
		return CopySz;
	}
	*((uint32_t*)ptmp) = dLen;
	
	// LLOG("#I ptmp [0x%x] len[%d]\n",ptmp,*((uint32_t*)ptmp));
	
	MEMCPY(&ptmp[sizeof(uint32_t)],pPkg,dLen);
	CopySz = dLen;
	//
	pBuf = pObj->pBuf;
	pBuf += (ItemSz*wIndex);	
	(*(void**)pBuf) = ptmp;			
	//
	wIndex++;
	wIndex = (wIndex < LoopSz)?wIndex:0;
	pObj->wIndex = wIndex;

	
	pObj->RWLock=0;
    return CopySz;
}

uint32_t MsgQueue_Read(tMsgQueue* pObj,uint32_t RBufSz, uint8_t* pRBuf){

	uint8_t* ptmp = NULL;
	
	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t LoopSz;

    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if( (pObj== NULL) || (pRBuf == NULL) || (RBufSz == 0) ){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
	if(CopySz ==  0){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}	
	
	pBuf = pObj->pBuf;
	pBuf+=(ItemSz*rIndex);
	
	ptmp = *((void**)pBuf);
	// LLOG("ptmp=0x%x \n",ptmp);
	CopySz = *((uint32_t*)ptmp);
	CopySz = (RBufSz > CopySz)?CopySz:RBufSz;
	MEMCPY(pRBuf,&ptmp[sizeof(uint32_t)],CopySz);
	L_FREE(ptmp);
	
	*((void**)pBuf) = 0;
	// update index
	rIndex++;
	rIndex = (rIndex < LoopSz)?rIndex:0;
	pObj->rIndex = rIndex;

	
	pObj->RWLock=0;
    return CopySz;
}

uint32_t MsgQueue_Reset(tMsgQueue* pObj){

	uint8_t* ptmp = NULL;
	
	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if(pObj== NULL){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1;
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);
	
	if(CopySz ==  0){
		LLOG_ERR();
		if(pObj->wIndex == pObj->rIndex){
			pObj->wIndex = 0;
			pObj->rIndex = 0;
		}	
		pObj->RWLock = 0;
		return CopySz;
	}	
	
	for(i=0;i<CopySz;i++){ // clean all;
		pBuf = pObj->pBuf;
		pBuf+=(ItemSz*rIndex);	
		
		ptmp = *((void**)pBuf);
		L_FREE(ptmp);
		*((void**)pBuf) = 0;
		
		rIndex++;// update index
		rIndex = (rIndex < LoopSz)?rIndex:0;
		pObj->rIndex = rIndex;		
	}

	if(pObj->wIndex == pObj->rIndex){
		pObj->wIndex = 0;
		pObj->rIndex = 0;
	}
	else{
		LLOG_ERR();
	}

	pObj->RWLock=0;
    return CopySz;

}

uint32_t MsgQueue_GetNextPkgSz(tMsgQueue* pObj){

	uint8_t* ptmp = NULL;
	
	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t LoopSz;

    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if( pObj== NULL){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
	if(CopySz ==  0){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}	
	
	pBuf = pObj->pBuf;
	pBuf+=(ItemSz*rIndex);
	
	ptmp = *((void**)pBuf);
	CopySz = *((uint32_t*)ptmp);
	
	pObj->RWLock=0;
    return CopySz;	
}

uint32_t MsgQueue_Peek(tMsgQueue* pObj,uint32_t RBufSz, uint8_t* pRBuf){

	uint8_t* ptmp = NULL;
	
	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t LoopSz;

    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if( (pObj== NULL) || (pRBuf == NULL) || (RBufSz == 0) ){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
	if(CopySz ==  0){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}	
	
	pBuf = pObj->pBuf;
	pBuf+=(ItemSz*rIndex);
	
	ptmp = *((void**)pBuf);
	// LLOG("ptmp=0x%x \n",ptmp);
	CopySz = *((uint32_t*)ptmp);
	CopySz = (RBufSz > CopySz)?CopySz:RBufSz;
	MEMCPY(pRBuf,&ptmp[sizeof(uint32_t)],CopySz);


	pObj->RWLock=0;
    return CopySz;
}

uint32_t MsgQueue_DorpOne(tMsgQueue* pObj){

	uint8_t* ptmp = NULL;
	
	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t LoopSz;

    uint32_t CopySz;
	uint32_t ItemSz;
    
	CopySz=0;
    if( pObj== NULL){
        return CopySz;
    }
	
	#if CC_BFIFO_RWLOCK_OC
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock = 1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->ItemNum;
	ItemSz = pObj->ItemSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
	if(CopySz ==  0){	
		LLOG_ERR();
		pObj->RWLock=0;
		return CopySz;
	}
	
	pBuf = pObj->pBuf;
	pBuf+=(ItemSz*rIndex);
	
	ptmp = *((void**)pBuf);
	// LLOG("ptmp=0x%x \n",ptmp);
	CopySz = *((uint32_t*)ptmp);

	L_FREE(ptmp);
	
	*((void**)pBuf) = 0;

	rIndex++;
	rIndex = (rIndex < LoopSz)?rIndex:0;
	pObj->rIndex = rIndex;

	pObj->RWLock=0;
    return CopySz;
}

#endif

